﻿using System;
using Kaleida.ServiceMonitor.Model.Statistics;
using NUnit.Framework;

namespace Kaleida.UnitTests.Model.Statistics
{
    [TestFixture]
    public class ProcessingStatisticsTests
    {
        [Test]
        [ExpectedException(typeof(ArgumentOutOfRangeException), ExpectedMessage="Duration cannot be negative\r\nParameter name: duration\r\nActual value was -10000.")]
        public void TestNegativeDurationThrowsException()
        {
            var stats = new ProcessingStatistics("Name1", "Description1");
            stats.IncrementSuccessCount(TimeSpan.FromMilliseconds(-1));
        }

        [Test]
        public void TestDurationRoundedToZeroIsPlacedInOneMillisecondBucket()
        {
            var stats = new ProcessingStatistics("Name1", "Description1");
            stats.IncrementSuccessCount(TimeSpan.FromMilliseconds(0.2));
            Assert.AreEqual("(1, 1)", string.Join(",", stats.GetResponseTimeDistribution()));
        }


        [Test]
        public void TestGetResponseTimePercentile()
        {
            var stats = new ProcessingStatistics("Name1", "Description1");

            for (int i = 0; i <  3; i++) stats.IncrementSuccessCount(TimeSpan.FromMilliseconds(1));
            for (int i = 0; i < 13; i++) stats.IncrementSuccessCount(TimeSpan.FromMilliseconds(2));
            for (int i = 0; i <  9; i++) stats.IncrementSuccessCount(TimeSpan.FromMilliseconds(3));
            for (int i = 0; i <  5; i++) stats.IncrementSuccessCount(TimeSpan.FromMilliseconds(4));
            for (int i = 0; i <  3; i++) stats.IncrementSuccessCount(TimeSpan.FromMilliseconds(5));
            for (int i = 0; i <  2; i++) stats.IncrementSuccessCount(TimeSpan.FromMilliseconds(6));
            for (int i = 0; i <  2; i++) stats.IncrementSuccessCount(TimeSpan.FromMilliseconds(7));
            for (int i = 0; i <  1; i++) stats.IncrementSuccessCount(TimeSpan.FromMilliseconds(8));
            for (int i = 0; i <  1; i++) stats.IncrementSuccessCount(TimeSpan.FromMilliseconds(9));
            for (int i = 0; i <  1; i++) stats.IncrementSuccessCount(TimeSpan.FromMilliseconds(10));

            Assert.AreEqual(40, stats.SuccessCount);

            var percentiles = stats.GetResponseTimePercentiles(new[] {90m, 99m, 50m});

            Assert.AreEqual(TimeSpan.FromMilliseconds(7), percentiles[0].Value);
            Assert.AreEqual(TimeSpan.FromMilliseconds(10), percentiles[1].Value);
            Assert.AreEqual(TimeSpan.FromMilliseconds(3), percentiles[2].Value);
        }

        [Test]
        public void TestGetResponseTimePercentileReturnsNullIfNoSuccesfulRequest()
        {
            var stats = new ProcessingStatistics("Name1", "Description1");
            Assert.AreEqual(null, stats.GetResponseTimePercentiles(new[] { 50m })[0].Value);
        }

        [Test]
        public void TestGetResponseTimePercentileIgnoredFailures()
        {
            var stats = new ProcessingStatistics("Name1", "Description1");
            stats.IncrementSuccessCount(TimeSpan.FromMilliseconds(1));
            stats.IncrementFailureCount();

            var percentiles = stats.GetResponseTimePercentiles(new[] { 0m, 50m, 100m });

            Assert.AreEqual(TimeSpan.FromMilliseconds(1), percentiles[0].Value);
            Assert.AreEqual(TimeSpan.FromMilliseconds(1), percentiles[1].Value);
            Assert.AreEqual(TimeSpan.FromMilliseconds(1), percentiles[2].Value);
        }
    }
}










